﻿//-----------------------------------------------------------------------------------------
// <copyright file="Orientation3D.cs" company="Jakub Florczyk (www.jakubflorczyk.pl)">
//      Copyright © 2009 Jakub Florczyk (www.jakubflorczyk.pl)
//      http://samsungmobilesdknet.codeplex.com
// </copyright>
//-----------------------------------------------------------------------------------------

namespace SamsungMobileSDKNET
{
    using System.Runtime.InteropServices;

    /// <summary>
    /// Function signature for 3D Orientation event handlers.
    /// </summary>
    /// <param name="data">3D Orientation vector data.</param>
    public delegate void Orientation3DEventHandler(Orientation3DPosition data);

    /// <summary>
    /// 3D Orientation vector data.
    /// </summary>
    /// <remarks>
    /// Given a phone lying face-up on a horizontal plane, the longitudinal axis runs the length of the phone; the lateral axis runs through the width of the phone, and the vertical axis runs top to bottom through the phone.
    /// </remarks>
    [StructLayout(LayoutKind.Sequential)]
    public struct Orientation3DPosition
    {
        /// <summary>
        ///  The yaw or azimuth angle, or rotation of the phone on its vertical axis. The value starts at 0 when the phone is facing magnetic north, and increases as the phone is turned clockwise. For example, a phone facing east has a heading of 90, the south 180, the west 270. The maximum heading value is 359.
        /// </summary>
        public short Heading;

        /// <summary>
        /// The angle the phone is rotated on its lateral axis. The value is an integer from -180 to 179. Pitch is zero when the phone is face up; it increases as the top edge of the phone is moved downward, and decreases when the top edge is moved upward.
        /// </summary>
        public short Pitch;

        /// <summary>
        /// The angle the phone is rotated on its longitudinal axis. The value is an integer from -90 to 90. Roll is zero when the phone is face up; it increases when the right edge of the phone is moved downward, and decreases when the right edge of the phone is moved upward.
        /// </summary>
        public short Roll;

        /// <summary>
        /// Calibration level percentage.
        /// </summary>
        /// <remarks>
        /// Values are from 0-100, with 0 = not calibrated, and 100 = fully calibrated. 
        /// </remarks>
        public ushort Accuracy;
    }

    /// <summary>
    /// Specifies the capabilities of the 3D Orientation device.
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct Orientation3DCapabilities
    {
        /// <summary>
        /// The vector sampling time, in milliseconds.
        /// </summary>
        public uint CallbackPeriod;
    }

    /// <summary>
    /// Samsung 3D Orientation API.
    /// </summary>
    /// <remarks>
    /// The 3D Orientation API can estimate the relative position of a phone in 3D space. It calculates these values using a combination of magnetic compass and accelerometer sensor data.
    /// <br/>
    /// Note that when the phone is powering down or under influence of external magnetic field, the 3D Orientation API can provide inaccurate values.
    /// </remarks>
    public class Orientation3D
    {
        /// <summary>
        /// Gets the capabilities of the 3D Orientation device.
        /// </summary>
        /// <param name="capabilities">A pointer to an <see cref="T:SamsungMobileSDKNET.Orientation3DCapabilities"/> structure that receives the capabilities of the 3D Orientation device.</param>
        /// <returns>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.Success"/> on success
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorInvalidParameter"/> if the input parameter is NULL
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorDeviceNotFound"/> if the device is not present or supported
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorCannonActivateServer"/> if the sensor server cannot be started
        /// </returns>
        [DllImport(Common.DllName, EntryPoint = "Smi3DOrientationGetCapabilities")]
        public static extern ResultCode GetCapabilities(
            [Out] out Orientation3DCapabilities capabilities);

        /// <summary>
        /// Gets the phone's current 3D orientation.
        /// </summary>
        /// <param name="data">A pointer to an <see cref="T:SamsungMobileSDKNET.Orientation3DPosition"/> structure that receives the 3D orientation of the phone.</param>
        /// <returns>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.Success"/> on success
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorInvalidParameter"/> if the input parameter is NULL
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorDeviceNotFound"/> if the device is not present or supported
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorUnknown"/> for all other failures
        /// </returns>
        [DllImport(Common.DllName, EntryPoint = "Smi3DOrientationGetPosition")]
        public static extern ResultCode GetPosition(
            [Out] out Orientation3DPosition data);

        /// <summary>
        /// Starts receiving 3D Orientation data periodically.
        /// </summary>
        /// <param name="period">The callback interval.</param>
        /// <param name="handler">The callback function for every period interval.</param>
        /// <returns>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.Success"/> on success
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorInvalidParameter"/> if the handler input parameter is NULL
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorDeviceNotFound"/> if the device is not present or supported
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorCannonActivateServer"/> if the sensor server cannot be started 
        /// </returns>
        /// <remarks>
        /// The period interval must be a multiple of the callbackPeriod specified in <see cref="T:SamsungMobileSDKNET.Orientation3DCapabilities"/>. If it is less than callbackPeriod, it will be set to callbackPeriod. If it is not a multiple of callbackPeriod, it will be truncated to fit the value. ( (period / callbackPeriod) * callbackPeriod )
        /// <br/><br/>
        /// Only one handler per process is allowed. Successive calls per process will replace the previous handler function and period.
        /// </remarks>
        [DllImport(Common.DllName, EntryPoint = "Smi3DOrientationRegisterHandler")]
        public static extern ResultCode RegisterHandler(
            [In] uint period,
            [In] Orientation3DEventHandler handler);

        /// <summary>
        /// Stops receiving periodic 3D Orientation data.
        /// </summary>
        /// <returns>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.Success"/> on success
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorDeviceNotFound"/> if the device is not present or supported
        /// <br/>
        /// <see cref="F:SamsungMobileSDKNET.ResultCode.ErrorCannonActivateServer"/> if the sensor server cannot be started
        /// </returns>
        [DllImport(Common.DllName, EntryPoint = "Smi3DOrientationUnregisterHandler")]
        public static extern ResultCode UnregisterHandler();
    }
}
